package com.tmt.im.manager.controller.api;

import com.tmt.im.manager.controller.vo.*;
import com.tmt.im.manager.helper.PrincipalHelper;
import com.tmt.im.manager.interfaces.IYunXinInterface;
import com.tmt.im.manager.service.IMFriendApplyService;
import com.tmt.im.manager.service.IMFriendIgniteService;
import com.tmt.springboot.common.restful.ExecuteResult;
import com.tmt.springboot.common.restful.IExecuteResult;
import com.tmt.springboot.common.restful.ResultWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteSemaphore;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.text.MessageFormat;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 好友控制器
 *
 * @Description TODO
 * @Author wuyi
 * @Date 2024/8/3 21:20
 * @Version 1.0
 **/
@Async("asyncTaskExecutor")
@Tag(name = "好友相关接口", description = "好友申请、审核、查询、删除等相关接口")
@RestController
@RequestMapping("${api-url-prefix}/friend")
public class FriendController {
    private final IMFriendIgniteService imFriendService;

    private final IMFriendApplyService imFriendApplyService;

    private final IYunXinInterface iYunXinInterface;

    private final Ignite ignite;

    public FriendController(IMFriendIgniteService imFriendService,
                            IMFriendApplyService imFriendApplyService,
                            IYunXinInterface iYunXinInterface,
                            Ignite ignite) {
        this.imFriendService = imFriendService;
        this.imFriendApplyService = imFriendApplyService;
        this.iYunXinInterface = iYunXinInterface;
        this.ignite = ignite;
    }

    @Operation(summary = "好友申请接口",
            description = "当前用户向指定用户申请添加好友的接口（如果对方不需要审核，则自动成为好友)",
            operationId = "applyFriend",
            parameters = {
                    @Parameter(name = "vo", description = "希望加为好友的用户ID", required = true)
            })
    @PostMapping("/apply")
    public CompletableFuture<IExecuteResult<FriendApplyResponse>> applyFriend(@RequestBody @Validated FriendApplyRequest vo, Principal principal) {
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        String semaphoreName = MessageFormat.format("applyFriend_{0}_{1}", "" + currentUserId, "" + vo.getUserId());
        try (IgniteSemaphore semaphore = ignite.semaphore(
                semaphoreName, // Distributed semaphore name.
                1,        // Number of permits.
                true,      // Release acquired permits if node, that owned them, left topology.
                true       // Create if it doesn't exist.
        )) {
            if (semaphore.tryAcquire(3, TimeUnit.SECONDS)) {
                try {
                    IExecuteResult<FriendApplyResponse> result = imFriendService.applyFriend(vo, principal);
                    return CompletableFuture.completedFuture(result);
                } catch (Exception ex) {
                    return CompletableFuture.completedFuture(ExecuteResult.failure(ex.getMessage(), null));
                }
            } else {
                return CompletableFuture.completedFuture(ExecuteResult.failure("系统繁忙，请稍后再试", null));
            }
        } catch (Exception ex) {
            return CompletableFuture.completedFuture(ExecuteResult.failure("获取全局信号量异常：" + ex.getMessage(), null));
        }
    }

    @Operation(summary = "好友申请回复接口",
            description = "对好友申请的回复接口",
            operationId = "replyApply",
            parameters = {
                    @Parameter(name = "userId", description = "希望加为好友的用户ID", required = true)
            })
    @PostMapping("/apply/reply")
    public CompletableFuture<IExecuteResult<ResultWrapper<Boolean>>> replyApply
            (@RequestBody @Validated FriendApplyReplyVo vo, Principal principal) {
        String semaphoreName = MessageFormat.format("replyApply_{0}", "" + vo.getApplyId());
        try (IgniteSemaphore semaphore = ignite.semaphore(
                semaphoreName, // Distributed semaphore name.
                1,        // Number of permits.
                true,      // Release acquired permits if node, that owned them, left topology.
                true       // Create if it doesn't exist.
        )) {
            if (semaphore.tryAcquire(3, TimeUnit.SECONDS)) {
                IExecuteResult<Boolean> result = imFriendService.reviewApply(vo, principal);
                return CompletableFuture.completedFuture(ResultWrapper.from(result));
            } else {
                return CompletableFuture.completedFuture(ExecuteResult.failure("系统繁忙，请稍后再试", null));
            }
        } catch (Exception ex) {
            return CompletableFuture.completedFuture(ExecuteResult.failure("获取全局信号量异常：" + ex.getMessage(), null));
        }
    }

    @Operation(summary = "好友申请数量查询接口",
            description = "查询待审核的好友申请数量接口",
            operationId = "totalFriendApplyCount")
    @GetMapping("/applyCount")
    public CompletableFuture<IExecuteResult<ApplyTotalInfo>> totalFriendApplyCount(Principal principal) {
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        ApplyTotalInfo totalInfo = imFriendApplyService.countByReviewTimeIsNullAndTargetId(currentUserId);
        return CompletableFuture.completedFuture(ExecuteResult.success(totalInfo));
    }

    @Operation(summary = "修改好友备注(别名)接口",
            description = "修改好友备注(别名)接口",
            operationId = "updateFriend",
            parameters = {
                    @Parameter(name = "vo", description = "好友信息更新请求对象")
            })
    @PostMapping("/alias/update")
    public CompletableFuture<IExecuteResult<ResultWrapper<Boolean>>> updateFriend(@RequestBody UpdateFriendRequest
                                                                                          vo,
                                                                                  Principal principal) {
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        IExecuteResult<Boolean> result = imFriendService.updateFriend(currentUserId, vo);
        return CompletableFuture.completedFuture(ResultWrapper.from(result));
    }

    @Operation(summary = "删除好友接口",
            description = "删除好友接口",
            operationId = "deleteFriend",
            parameters = {
                    @Parameter(name = "request", description = "删除好友请求对象")
            })
    @PostMapping("/delete")
    public CompletableFuture<IExecuteResult<ResultWrapper<Boolean>>> deleteFriend(@RequestBody DeleteFriendRequest
                                                                                          request, Principal principal) {
        //强制设置deleteAll=true;
        request.setDeleteAll(true);
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        IExecuteResult<Boolean> result = imFriendService.deleteFriend(currentUserId, request);
        return CompletableFuture.completedFuture(ResultWrapper.from(result));
    }

    @Operation(summary = "黑名单管理接口",
            description = "将好友拉人或拉出黑名单",
            operationId = "pullInBlackBill",
            parameters = {
                    @Parameter(name = "request", description = "黑名单管理请求对象")
            })
    @PostMapping("/blackBill")
    public CompletableFuture<IExecuteResult<ResultWrapper<Boolean>>> pullInBlackBill
            (@RequestBody @Validated BlackBillRequest request, Principal principal) {
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        IExecuteResult<Boolean> result = imFriendService.pullInBlackBill(currentUserId, request);
        return CompletableFuture.completedFuture(ResultWrapper.from(result));
    }

    @Operation(summary = "查询黑名单列表接口",
            description = "查询黑名单列表接口",
            operationId = "listBlackBill",
            parameters = {
                    @Parameter(name = "request", description = "黑名单管理请求对象")
            })
    @PostMapping("/blackBill/list")
    public CompletableFuture<IExecuteResult<QueryBlackBillResponse>> listBlackBill(@RequestBody @Validated PageQueryRequest request,
                                                                                   Principal principal) {
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        IExecuteResult<QueryBlackBillResponse> result = imFriendService.listBlackBill(currentUserId, request, principal);
        return CompletableFuture.completedFuture(result);
    }

    @Operation(summary = "免打扰管理接口",
            description = "设置或解除好友的免打扰状态",
            operationId = "enableNoDisturbing",
            parameters = {
                    @Parameter(name = "request", description = "免打扰管理请求对象")
            })
    @PostMapping("/noDisturbing")
    public CompletableFuture<IExecuteResult<ResultWrapper<Boolean>>> enableNoDisturbing
            (@RequestBody @Validated NoDisturbingRequest request, Principal principal) {
        Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
        IExecuteResult<Boolean> result = imFriendService.enableNoDisturbing(currentUserId, request);
        return CompletableFuture.completedFuture(ResultWrapper.from(result));
    }

    @Operation(summary = "滑动查询接收到的好友申请列表接口",
            description = "滑动查询当前用户接收到的好友申请列表",
            operationId = "slideQueryReceivedFriendApplyList",
            parameters = {
                    @Parameter(name = "request", description = "滑动查询请求对象")
            })
    @PostMapping("/slideQuery/receivedApply")
    public CompletableFuture<IExecuteResult<SlideQueryFriendApplyResponse>> slideQueryReceivedFriendApplyList
            (@RequestBody SlideQueryRequest request,
             Principal principal) {
        IExecuteResult<SlideQueryFriendApplyResponse> result = imFriendService.slideQueryFriendApplyList(request, true, principal);
        return CompletableFuture.completedFuture(result);
    }

    @Operation(summary = "分页查询接收到的好友申请列表接口",
            description = "分页查询当前用户接收到的好友申请列表",
            operationId = "pageQueryReceivedFriendApplyList",
            parameters = {
                    @Parameter(name = "pageNo", description = "页序号，从0开始", required = true),
                    @Parameter(name = "pageSize", description = "每页数据记录条数，默认20条")
            })
    @GetMapping("/pageQuery/receivedApply")
    public CompletableFuture<IExecuteResult<PageQueryFriendApplyResponse>> pageQueryReceivedFriendApplyList
            (@RequestParam(value = "pageNo", defaultValue = "0") Integer pageIndex,
             @RequestParam(value = "pageSize", defaultValue = "20", required = false) Integer pageSize,
             Principal principal) {
        PageRequest pageable = PageRequest.of(pageIndex, pageSize);
        IExecuteResult<PageQueryFriendApplyResponse> result = imFriendService.pageQueryFriendApplyList(pageable, true, principal);
        return CompletableFuture.completedFuture(result);
    }

    @Operation(summary = "滑动查询发出的好友申请列表接口",
            description = "滑动查询当前用户发出的好友申请列表",
            operationId = "slideQuerySendFriendApplyList",
            parameters = {
                    @Parameter(name = "request", description = "滑动查询请求对象")
            })
    @GetMapping("/slideQuery/sendApply")
    @Deprecated
    public CompletableFuture<IExecuteResult<SlideQueryFriendApplyResponse>> slideQuerySendFriendApplyList
            (@RequestBody SlideQueryRequest request,
             Principal principal) {
        IExecuteResult<SlideQueryFriendApplyResponse> result = imFriendService.slideQueryFriendApplyList(request, false, principal);
        return CompletableFuture.completedFuture(result);
    }

    @Operation(summary = "分页查询发出的好友申请列表接口",
            description = "分页查询当前用户发出的好友申请列表",
            operationId = "pageQuerySendFriendApplyList",
            parameters = {
                    @Parameter(name = "pageNo", description = "页序号，从0开始", required = true),
                    @Parameter(name = "pageSize", description = "每页数据记录条数，默认20条")
            })
    @GetMapping("/pageQuery/sendApply")
    @Deprecated
    public CompletableFuture<IExecuteResult<PageQueryFriendApplyResponse>> pageQuerySendFriendApplyList
            (@RequestParam(value = "pageNo", defaultValue = "0") Integer pageIndex,
             @RequestParam(value = "pageSize", defaultValue = "20", required = false) Integer pageSize,
             Principal principal) {
        PageRequest pageable = PageRequest.of(pageIndex, pageSize);
        IExecuteResult<PageQueryFriendApplyResponse> result = imFriendService.pageQueryFriendApplyList(pageable, false, principal);
        return CompletableFuture.completedFuture(result);
    }

    @Operation(summary = "滑动查询好友列表接口",
            description = "滑动查询当前用户的好友列表",
            operationId = "slideQueryFriendList",
            parameters = {
                    @Parameter(name = "request", description = "滑动查询请求对象")
            })
    @PostMapping("/slideQuery/friendList")
    public CompletableFuture<IExecuteResult<SlideQueryFriendResponse>> slideQueryFriendList
            (@RequestBody SlideQueryRequest request,
             Principal principal) {
        IExecuteResult<SlideQueryFriendResponse> result = imFriendService.slideQueryFriendList(request, principal);
        return CompletableFuture.completedFuture(result);
    }

    @Operation(summary = "按条件滑动查询好友列表接口",
            description = "在当前用户的好友中按条件滑动查询好友信息接口",
            operationId = "slideQueryFriendByCondition",
            parameters = {
                    @Parameter(name = "request", description = "滑动条件查询请求对象")
            })
    @PostMapping("/slideQuery/condition")
    public CompletableFuture<IExecuteResult<SlideConditionQueryFriendResponse>> slideQueryFriendByCondition
            (@RequestBody @Validated SlideConditionQueryRequest request,
             Principal principal) {
        IExecuteResult<SlideConditionQueryFriendResponse> result = imFriendService.slideQueryFriendByCondition(request, principal);
        return CompletableFuture.completedFuture(result);
    }

}
